package com.cbg.es.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.cbg.dto.SelectedColListDTO;
import com.cbg.enums.EsCategoryTypeEnum;
import com.cbg.enums.EsSearchManageExceptionEnum;
import com.cbg.enums.MoveDirectionEnum;
import com.cbg.es.dto.EsCategoryDTO;
import com.cbg.es.dto.EsColEditDTO;
import com.cbg.es.dto.EsTableEditDTO;
import com.cbg.es.dto.EsTableListDTO;
import com.cbg.es.entity.*;
import com.cbg.es.service.*;
import com.cbg.es.vo.CategoryVO;
import com.cbg.utils.CollectionUtils;
import com.cbg.utils.StringUtils;
import com.cbg.vo.CategoryNameVO;
import com.cbg.vo.DirectionsVO;
import com.shuyuwl.core.enums.StatusEnum;
import com.shuyuwl.core.exception.SymServiceException;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author wangjuzheng
 * @date 2019-10-22
 **/
@Service
@Transactional(rollbackFor = SymServiceException.class)
public class EsServiceImpl implements IEsService {

    @Resource
    private IEsCategoryService esCategoryService;
    @Resource
    private IEsColService esColService;
    @Resource
    private IEsTableCategoryService esTableCategoryService;
    @Resource
    private IEsTableColService esTableColService;
    @Resource
    private IEsTableService esTableService;

    @Override
    public List<EsCategoryDTO> getEsCategoryDTOs(int categoryType) {

        //获取所有的的分类信息
        List<EsCategory> list = esCategoryService.findCategory(StatusEnum.OK.getCode());

        List<EsCategoryDTO> esCategoryDTOS = new ArrayList<>();
        if (CollectionUtils.isNotEmpty(list)) {
            for (EsCategory esCategory : list) {
                EsCategoryDTO esCategoryDTO = new EsCategoryDTO();
                //获取分类信息
                BeanUtils.copyProperties(esCategory, esCategoryDTO);
                // 类型区分(0表 1分类)
                esCategoryDTO.setType(EsCategoryTypeEnum.CATEGORY.getType());
                //唯一id
                esCategoryDTO.setId(esCategory.getId());

                esCategoryDTOS.add(esCategoryDTO);
            }

            //表信息
            if (categoryType == 0) {
                List<Long> ids = list.stream().map(EsCategory::getId).collect(Collectors.toList());
                // 根据分类id获取表信息
                List<EsTableCategory> esTableCategoryList = esTableCategoryService.getAllEsTableCategory(ids);
                if (CollectionUtils.isNotEmpty(esTableCategoryList)) {
                    for (EsTableCategory esTableCategory : esTableCategoryList) {
                        EsCategoryDTO esCategoryDTO1 = new EsCategoryDTO();
                        //唯一id
                        esCategoryDTO1.setId(formatCategoryTableIdStr(esTableCategory.getCategoryId(), esTableCategory.getId()));
                        // 父级id
                        esCategoryDTO1.setPid(esTableCategory.getCategoryId());
                        // 名称
                        esCategoryDTO1.setName(esTableCategory.getTableName());
                        // 类型区分(0表 1分类)
                        esCategoryDTO1.setType(EsCategoryTypeEnum.TABLE.getType());
                        esCategoryDTOS.add(esCategoryDTO1);
                    }
                }
            }
        }

        return esCategoryDTOS;
    }

    @Override
    public void updateCategoryDirections(DirectionsVO directionsVO) {

        //根据父级id获取分类信息
        List<EsCategory> esCategoryList = findCategory(directionsVO.getPid());
        //分类信息的验证
        EsCategory esCategory = checkEsCategory(directionsVO.getId());
        //移动位置的验证
        MoveDirectionEnum moveDirectionEnum = MoveDirectionEnum.getDirectionByCode(directionsVO.getDirectionType());
        //请选择正确的移动方向
        if (moveDirectionEnum == null) {
            throw new SymServiceException(EsSearchManageExceptionEnum.MOVE_DIRECTION_NULL.getCode(), EsSearchManageExceptionEnum.MOVE_DIRECTION_NULL.getMsg());
        }
        //获取需要移动类的下标
        int currentIndex = esCategoryList.indexOf(esCategory);
        //需要移动的分类不存在
        if (currentIndex == -1) {
            throw new SymServiceException(EsSearchManageExceptionEnum.CATEGORY_INDEX_NULL.getCode(), EsSearchManageExceptionEnum.CATEGORY_INDEX_NULL.getMsg());
        }

        //分类位置移动
        moveCategoryDirections(currentIndex, esCategory, moveDirectionEnum, esCategoryList);
    }

    @Override
    public EsCategoryDTO updateCategoryName(CategoryNameVO categoryNameVO) {

        //参数验证
        EsCategory esCategory = checkEsCategory(categoryNameVO.getId());
        //名称是否存在的验证
        List<EsCategory> list = esCategoryService.findByPidAndCategoryName(esCategory.getPid(), categoryNameVO.getName().trim());
        //分类名称已存在
        if (CollectionUtils.isNotEmpty(list)) {
            if ((list.size() > 1 || !list.get(0).getId().equals(esCategory.getId()))) {
                throw new SymServiceException(EsSearchManageExceptionEnum.ERROR_CATEGORY_NAME_NOT_NULL.getCode(), EsSearchManageExceptionEnum.ERROR_CATEGORY_NAME_NOT_NULL.getMsg());
            }
        }
        //全景分类名称
        esCategory.setName(categoryNameVO.getName().trim());
        //全景分类名称的修改
        esCategoryService.save(esCategory);

        return getEsCategoryDTO(esCategory, EsCategoryTypeEnum.CATEGORY.getType());
    }


    @Override
    public EsCategoryDTO addCategory(CategoryVO categoryVO) {

        //父级id的判断
        if (categoryVO.getPid() != null) {
            checkEsCategory(categoryVO.getPid());
        }
        Long pid = categoryVO.getPid() == null ? 0 : categoryVO.getPid();
        //名称是否存在的验证
        List<EsCategory> list = esCategoryService.findByPidAndCategoryName(pid, categoryVO.getName().trim());
        //分类名称已存在
        if (CollectionUtils.isNotEmpty(list)) {
            throw new SymServiceException(EsSearchManageExceptionEnum.ERROR_CATEGORY_NAME_NOT_NULL.getCode(), EsSearchManageExceptionEnum.ERROR_CATEGORY_NAME_NOT_NULL.getMsg());
        }
        // 分类的添加
        EsCategory category = new EsCategory();
        // 父级id
        category.setPid(pid);
        // 名称
        category.setName(categoryVO.getName().trim());
        //排序
        Integer sort = getMaxSort(categoryVO.getPid());
        category.setSort(sort == null ? 1 : sort + 1);
        //图标
        category.setIcon(categoryVO.getIcon());
        //状态
        category.setStatus(StatusEnum.OK.getCode());
        esCategoryService.save(category);

        //显示表的添加
        if (CollectionUtils.isNotEmpty(categoryVO.getIds())) {
            addEsTableCategory(category.getId(), categoryVO.getIds());
        }

        return getEsCategoryDTO(category, EsCategoryTypeEnum.CATEGORY.getType());
    }

    @Override
    public void addEsTableCategory(Long categoryId, List<Long> tableIds) {

        //分类id的验证
        checkEsCategory(categoryId);
        //请选择需要添加的表
        if (CollectionUtils.isEmpty(tableIds)) {
            throw new SymServiceException(EsSearchManageExceptionEnum.ERROR_TABLE_IDS_NULL.getCode(), EsSearchManageExceptionEnum.ERROR_TABLE_IDS_NULL.getMsg());
        }

        // 分类对应表的添加
        tableIds.forEach(tableId -> {
            //验证表是否存在
            EsTable esTable = esTableService.checkEsTable(tableId);

            //展示表的添加
            EsTableCategory esTableCategory = new EsTableCategory();
            // 表ID
            esTableCategory.setTableId(esTable.getId());
            // 全景分类ID
            esTableCategory.setCategoryId(categoryId);
            // 排序
            Integer sort = esTableCategoryService.getMaxSort(categoryId);
            esTableCategory.setSort(sort == null ? 1 : sort + 1);
            // 表显示名
            esTableCategory.setTableName(esTable.getTableNameAlias());
            // 状态
            esTableCategory.setStatus(StatusEnum.OK.getCode());
            esTableCategoryService.save(esTableCategory);

            // 分类对应表的列添加
            addEsTableCol(esTableCategory.getId(), esTable.getTableName());
        });
    }

    @Override
    public void deleteCategory(Long categoryId) {

        //验证并获取用户信息
        EsCategory esCategory = checkEsCategory(categoryId);
        //删除全景通查展示表与展示表字段信息
        esTableCategoryService.deleteByCategoryId(categoryId);

        //根据父级id获取所属的分类信息
        List<EsCategory> list = esCategoryService.findByPid(categoryId, StatusEnum.OK.getCode());
        if (CollectionUtils.isNotEmpty(list)) {
            list.forEach(esCategory1 -> deleteCategory(esCategory1.getId()));
        }

        //分类的删除
        esCategory.setStatus(StatusEnum.DELETE.getCode());
        //分类的删除
        esCategoryService.save(esCategory);
    }


    @Override
    public List<EsTableListDTO> getEsTables(Long categoryId) {

        //获取列表信息
        List<EsTable> esTables = esTableService.findAllEsTable(StatusEnum.OK.getCode());
        List<EsTableListDTO> list = new ArrayList<>();
        if (CollectionUtils.isNotEmpty(esTables)) {

            //当分类id存在时
            if (categoryId != null) {

                checkEsCategory(categoryId);
                //根据分类id获取展示表信息
                List<EsTableCategory> esTableCategoryList = esTableCategoryService.findByCategoryId(categoryId);
                //去除已经选的分类信息
                if (CollectionUtils.isNotEmpty(esTableCategoryList)) {
                    List<Long> ids = esTableCategoryList.stream().map(EsTableCategory::getTableId).collect(Collectors.toList());
                    esTables = esTables.stream().filter(esTable -> !ids.contains(esTable.getId())).collect(Collectors.toList());
                }
            }

            esTables.forEach(esTable -> {
                EsTableListDTO esTableListDTO = getEsTableListDTO(esTable, esTable.getTableName(), esTable.getStatus());
                list.add(esTableListDTO);

            });
        }
        return list;
    }

    @Override
    public List<SelectedColListDTO> selectedTableCategory(Long tableCategoryId) {

        //根据展示表id验证展示信息是否存在
        checkEsTableCategory(tableCategoryId);
        //根据展示表id获取显示的列信息
        return esTableColService.selectedTableCategory(tableCategoryId);
    }

    @Override
    public void saveEsTableCategory(Long categoryId, List<EsTableEditDTO> list) {

        //验证并获取用户信息
        checkEsCategory(categoryId);

        if (CollectionUtils.isNotEmpty(list)) {
            List<Long> ids = new ArrayList<>();
            for (int i = 0; i < list.size(); i++) {

                EsTableEditDTO esTableEditDTO = list.get(i);
                //表的保存
                EsTableCategory esTableCategory = checkEsTableCategory(formatCategoryTableId(esTableEditDTO.getId()));
                //表显示名
                esTableCategory.setTableName(esTableEditDTO.getTableNameAlias());
                //状态
                esTableCategory.setStatus(esTableEditDTO.getStatus());
                //排序
                esTableCategory.setSort(i + 1);
                esTableCategoryService.save(esTableCategory);

                ids.add(esTableCategory.getId());
            }

            //删除其余的表
            esTableCategoryService.deleteByCategoryIdAndTableCategoryIdNeqIn(categoryId, ids);
        }
    }

    @Override
    public List<EsTableListDTO> selectedCategory(Long categoryId) {

        //根据分类id获取展示表信息
        checkEsCategory(categoryId);
        List<EsTableListDTO> listDTOS = esTableCategoryService.selectedCategory(categoryId);
        if (CollectionUtils.isNotEmpty(listDTOS)) {
            listDTOS.forEach(esTableListDTO -> esTableListDTO.setId(formatCategoryTableIdStr(categoryId, (Long) esTableListDTO.getId())));
        }
        return listDTOS;
    }

    @Override
    public void saveEsTableCol(Long tableCategoryId, List<EsColEditDTO> list) {

        //根据展示表id验证展示信息是否存在
        checkEsTableCategory(tableCategoryId);

        //当存在列信息时则保存
        if (CollectionUtils.isNotEmpty(list)) {
            for (int i = 0; i < list.size(); i++) {
                EsColEditDTO esColListDTO = list.get(i);
                EsTableCol esTableCol = esTableColService.findById(esColListDTO.getId());
                //列显示名称
                esTableCol.setColName(esColListDTO.getColNameAlias());
                //状态
                esTableCol.setStatus(esColListDTO.getStatus());
                //排序
                esTableCol.setSort(i + 1);
                esTableColService.save(esTableCol);
            }

        }
    }

    @Override
    public Long formatCategoryTableId(String categoryTableIdStr) {

        if (StringUtils.isBlank(categoryTableIdStr)) {
            return null;
        }

        if (!categoryTableIdStr.contains(StringUtils.UNDERLINE)) {
            return Long.valueOf(categoryTableIdStr);
        }
        String str = categoryTableIdStr.substring(categoryTableIdStr.indexOf(StringUtils.UNDERLINE) + 1);
        return Long.valueOf(str);
    }

    /**
     * 全景展示列的添加
     *
     * @param tableCategoryId 展示表id
     * @param tableName       表名称
     */
    private void addEsTableCol(Long tableCategoryId, String tableName) {

        // 根据表名获取列信息
        List<EsCol> esCols = esColService.findByTableName(tableName);
        // 分类对应表的列添加
        if (CollectionUtils.isNotEmpty(esCols)) {
            esCols.forEach(esCol -> {
                EsTableCol esTableCol = new EsTableCol();
                // 列id
                esTableCol.setColId(esCol.getId());
                // 分类_显示表id
                esTableCol.setEsTableCategoryId(tableCategoryId);
                // 列名
                esTableCol.setColName(esCol.getColNameAlias());
                // 排序
                esTableCol.setSort(esCol.getSort());
                // 状态
                esTableCol.setStatus(StatusEnum.OK.getCode());
                esTableColService.save(esTableCol);
            });
        }
    }

    /**
     * 分类的位移
     *
     * @param currentIndex  移动类在所属分类下的下标
     * @param esCategory    需要移动类信息
     * @param directionEnum 移动位置枚举
     * @param list          分类列表信息
     */
    private void moveCategoryDirections(int currentIndex, EsCategory esCategory, MoveDirectionEnum
            directionEnum, List<EsCategory> list) {

        switch (directionEnum) {
            case UP:
                //上移，需要和前一个商品交换下标
                if (currentIndex == 0) {
                    //已经是第一个，无法上移
                    throw new SymServiceException(EsSearchManageExceptionEnum.ERROR_MOVE_DIRECTION_TOP.getCode(), EsSearchManageExceptionEnum.ERROR_MOVE_DIRECTION_TOP.getMsg());
                }
                EsCategory previous = list.get(currentIndex - 1);
                previous.setSort(currentIndex);
                esCategory.setSort(currentIndex - 1);
                esCategoryService.save(previous);
                esCategoryService.save(esCategory);
                break;
            case DOWN:
                //下移
                if (currentIndex == list.size() - 1) {
                    //已经是最后一个，无法下移
                    throw new SymServiceException(EsSearchManageExceptionEnum.ERROR_MOVE_DIRECTION_DOWN.getCode(), EsSearchManageExceptionEnum.ERROR_MOVE_DIRECTION_DOWN.getMsg());
                }
                EsCategory next = list.get(currentIndex + 1);
                next.setSort(currentIndex);
                esCategory.setSort(currentIndex + 1);
                esCategoryService.save(next);
                esCategoryService.save(esCategory);

                break;
            case TOP:
                //置顶
                if (currentIndex == 0) {
                    //已经是第一个，无法上移
                    throw new SymServiceException(EsSearchManageExceptionEnum.ERROR_MOVE_DIRECTION_TOP.getCode(), EsSearchManageExceptionEnum.ERROR_MOVE_DIRECTION_TOP.getMsg());
                }
                esCategory.setSort(list.get(0).getSort());
                esCategoryService.save(esCategory);

                for (int i = 0; i < currentIndex; i++) {
                    EsCategory newEsCategory = list.get(i);
                    newEsCategory.setSort(newEsCategory.getSort() + 1);
                    esCategoryService.save(newEsCategory);
                }
                break;
            case LAST:
                //置底
                if (currentIndex == list.size() - 1) {
                    //已经是最后一个，无法下移
                    throw new SymServiceException(EsSearchManageExceptionEnum.ERROR_MOVE_DIRECTION_DOWN.getCode(), EsSearchManageExceptionEnum.ERROR_MOVE_DIRECTION_DOWN.getMsg());
                }
                esCategory.setSort(list.get(list.size() - 1).getSort());
                esCategoryService.save(esCategory);

                for (int i = currentIndex + 1; i < list.size(); i++) {
                    EsCategory newEsCategory = list.get(i);
                    newEsCategory.setSort(newEsCategory.getSort() - 1);
                    esCategoryService.save(esCategory);
                }
                break;
            default:
                break;
        }
    }

    /**
     * 分类信息的验证
     *
     * @param id 分类id
     * @return 分类详情
     */
    private EsCategory checkEsCategory(Long id) {

        //根据id获取对应的分类详情
        EsCategory esCategory = getEsCategory(id);
        //分类不存在
        if (esCategory == null) {
            throw new SymServiceException(EsSearchManageExceptionEnum.ERROR_CATEGORY_NULL.getCode(), EsSearchManageExceptionEnum.ERROR_CATEGORY_NULL.getMsg());
        }
        return esCategory;
    }

    /**
     * 根据展示表id验证展示信息是否存在
     *
     * @param tableCategoryId 展示表id
     */
    private EsTableCategory checkEsTableCategory(Long tableCategoryId) {

        //表id不存在
        if (tableCategoryId == null) {
            throw new SymServiceException(EsSearchManageExceptionEnum.ERROR_TABLE_ID_NULL.getCode(), EsSearchManageExceptionEnum.ERROR_TABLE_ID_NULL.getMsg());
        }

        EsTableCategory esTableCategory = esTableCategoryService.findById(tableCategoryId);
        //表信息不存在
        if (esTableCategory == null) {
            throw new SymServiceException(EsSearchManageExceptionEnum.ERROR_TABLE_NULL.getCode(), EsSearchManageExceptionEnum.ERROR_TABLE_NULL.getMsg());
        }
        return esTableCategory;
    }

    /**
     * 根据id获取对应的分类详情
     *
     * @param categoryId 分类id
     * @return 分类信息
     */
    private EsCategory getEsCategory(Long categoryId) {

        //分类id不存在
        if (categoryId == null) {
            throw new SymServiceException(EsSearchManageExceptionEnum.ERROR_CATEGORY_ID_NULL.getCode(), EsSearchManageExceptionEnum.ERROR_CATEGORY_ID_NULL.getMsg());
        }
        return esCategoryService.findByIdAndStatus(categoryId, StatusEnum.OK.getCode());
    }


    /**
     * 根据父级id获取分类信息
     *
     * @param pid 分类id
     * @return 分类信息list
     */
    private List<EsCategory> findCategory(Long pid) {

        //获取一级分类信息
        if (pid == null) {
            return esCategoryService.findByPid(0L, StatusEnum.OK.getCode());
        }
        //根据父级id获取所属的分类id信息
        return esCategoryService.findByPid(pid, StatusEnum.OK.getCode());
    }

    /**
     * 根据父级id获取最大的排序
     *
     * @param pid 父级id
     * @return 排序
     */
    private Integer getMaxSort(Long pid) {

        if (pid == null) {
            return esCategoryService.getMaxSort(0L, StatusEnum.OK.getCode());
        }
        return esCategoryService.getMaxSort(pid, StatusEnum.OK.getCode());
    }

    /**
     * 获取表信息DTO
     *
     * @param esTable   表信息
     * @param tableName 表显示名称
     * @param status    状态
     * @return 表信息DTO
     */
    private EsTableListDTO getEsTableListDTO(EsTable esTable, String tableName, Byte status) {

        EsTableListDTO esTableListDTO = new EsTableListDTO();
        //表id
        esTableListDTO.setTableId(esTable.getId());
        //表名
        esTableListDTO.setTableName(esTable.getTableName());
        //表注释
        esTableListDTO.setTableNameCn(esTable.getTableNameCn());
        //表显示名称
        esTableListDTO.setTableNameAlias(tableName);
        //状态
        esTableListDTO.setStatus(status);
        return esTableListDTO;
    }

    /**
     * 获取分类模型
     *
     * @param esCategory 分类信息
     * @param type       类型
     * @return 分类模型
     */
    private EsCategoryDTO getEsCategoryDTO(EsCategory esCategory, Integer type) {
        EsCategoryDTO esCategoryDTO = JSONObject.parseObject(JSONObject.toJSONString(esCategory), EsCategoryDTO.class);
        esCategoryDTO.setType(type);
        return esCategoryDTO;
    }

    /**
     * 格式化展示表id
     *
     * @param categoryId      分类id
     * @param categoryTableId 展示表id
     * @return 格式化后的展示表id1
     */
    private String formatCategoryTableIdStr(Long categoryId, Long categoryTableId) {
        return categoryId + StringUtils.UNDERLINE + categoryTableId;
    }
//
//    /**
//     * 验证分类民名称是否存在
//     *
//     * @param categoryPid  父级id
//     * @param categoryName 分类名称
//     */
//    private void checkCategoryName(Long categoryPid, String categoryName) {
//
//        //根据分类名称查询条数
//        int count = esCategoryService.countByPidAndCategoryName(categoryPid, categoryName.trim());
//        if (count > 0) {
//            throw new SymServiceException(200251, "分类名称已存在");
//        }
//    }
}
